#import "RNSourceListCellWithCountBadge.h"
#import "RNConstants.h"
#import "RNHoverLinkButtonCell.h"
#import "NSCell+SRAdditions.h"
#import "RNSourceListPlaceholder.h"
#import "NSShadow+MCAdditions.h"

static NSDictionary *badgeAttributes;
static NSUInteger const verticalBadgePadding = 4;
static NSUInteger const rightBadgePadding = 3;
static NSUInteger const leftBadgePadding = 5;
static NSUInteger const horizontalBadgeTextPadding = 7;
static NSUInteger const badgePathXRadius = 7;
static NSUInteger const badgePathYRadius = 8;

static NSUInteger const iconLength = 16;
static NSUInteger const iconPadding = 3;

static NSColor *badgeColor, *badgeColorHighlighted, *badgeColorInactive;
static NSColor *badgeTextColor, *badgeTextColorHighlighted, *badgeTextColorInactive;

#pragma mark -
@interface RNSourceListCellWithCountBadge (RNSourceListCellWithCountBadgePrivateMethods)
-(void)initializeCell;
-(NSAttributedString *)attributedBadgeString;
@end


#pragma mark -
@implementation RNSourceListCellWithCountBadge

@synthesize itemCount = itemCount_;
@synthesize icon = icon_;
@synthesize hoverButtonCell = hoverButtonCell_;

+(void)initialize {
    badgeAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont fontWithName:@"Helvetica-Bold" size:11], NSFontAttributeName, nil];
    badgeColor = [NSColor colorWithCalibratedRed:.53 green:.60 blue:.74 alpha:1.0];
    badgeColorHighlighted = [NSColor whiteColor];
    badgeColorInactive = [NSColor colorWithCalibratedWhite:0.62 alpha:1.0];
    badgeTextColor = [NSColor whiteColor];
    badgeTextColorHighlighted = [NSColor colorWithCalibratedRed:.51 green:.58 blue:.72 alpha:1.0];
    badgeTextColorInactive = [NSColor colorWithCalibratedWhite:0.62 alpha:1.0];
}

-(id)initTextCell:(NSString *)aString {
    if (!(self = [super initTextCell:aString]))
        return nil;
    [self initializeCell];
    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder {
    if (!(self = [super initWithCoder:aDecoder]))
        return nil;
    [self initializeCell];
    return self;
}

-(id)copyWithZone:(NSZone *)zone {
    RNSourceListCellWithCountBadge *cell = [super copyWithZone:zone];
    [cell initializeCell];
    return cell;
}

-(void)initializeCell {
    hoverButtonCell_ = [[RNHoverLinkButtonCell alloc] initTextCell:@"Click to add a list"];
    NSDictionary *normalAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSColor colorWithCalibratedRed:0.49 green:0.561 blue:0.631 alpha:1.0], NSForegroundColorAttributeName, [NSFont controlContentFontOfSize:11.0f], NSFontAttributeName, [[NSShadow alloc] initWithColor:[NSColor colorWithCalibratedWhite:1.0f alpha:1.0f] offset:NSMakeSize(0, -1) blurRadius:1.0f], NSShadowAttributeName, nil];
    [hoverButtonCell_ setNormalAttributes:normalAttributes];
    NSMutableDictionary *hoverAttributes = [NSMutableDictionary dictionaryWithDictionary:normalAttributes];
    [hoverAttributes setValue:[NSNumber numberWithInteger:NSUnderlineStyleSingle | NSUnderlinePatternSolid] forKey:NSUnderlineStyleAttributeName];
    [hoverButtonCell_ setHoverAttributes:hoverAttributes];
    [hoverButtonCell_ setAction:@selector(displayNewItemSheetAndSelectList:)];
}

-(void)setObjectValue:(id <NSCopying>)object {
    if (![(NSObject *)object isKindOfClass:[NSDictionary class]]) {
        [super setObjectValue:object];
        return;
    }
    NSDictionary *objectDictionary = (NSDictionary *)object;
    [super setObjectValue:[objectDictionary valueForKey:RNTitleKey]];
    NSNumber *count = [objectDictionary valueForKey:@"itemCount"];
    [self setItemCount:(count == nil) ? -1 : [count integerValue]];
    [self setIcon:[objectDictionary valueForKey:@"icon"]];
}

-(void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
    if ([[self representedObject] isKindOfClass:[RNSourceListPlaceholder class]]) {
        [[self hoverButtonCell] drawInteriorWithFrame:[self titleRectForBounds:cellFrame] inView:controlView];
        return;
    }
    [super drawInteriorWithFrame:[self titleRectForBounds:cellFrame] inView:controlView];
        
    [[self icon] drawInRect:[self imageRectForBounds:cellFrame] fromRect:NSZeroRect operation:NSCompositeSourceAtop fraction:1.0 respectFlipped:YES hints:nil];

    if ([self itemCount] <= 0) 
        return;
    
    NSAttributedString *badgeText = [self attributedBadgeString];
    NSRect badgeRect = [self badgeRectForBounds:cellFrame];
    NSRect badgeTextRect = NSInsetRect(badgeRect, horizontalBadgeTextPadding, 0);
    NSBezierPath *badgePath = [NSBezierPath bezierPathWithRoundedRect:badgeRect xRadius:badgePathXRadius yRadius:badgePathYRadius];

    NSColor *currentBadgeColor = [NSApp isActive] ? badgeColor : badgeColorInactive;
    [([self isHighlighted] ? badgeColorHighlighted : currentBadgeColor) setFill];
    [badgePath fill];
    [badgeText drawInRect:badgeTextRect];
}

- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength {
    [super selectWithFrame:[self titleRectForBounds:aRect] inView:controlView editor:textObj delegate:anObject start:selStart length:selLength];
}

-(NSRect)titleRectForBounds:(NSRect)theRect {
    NSRect titleRect = [super titleRectForBounds:theRect];
    titleRect.size.width -= NSWidth([self badgeRectForBounds:theRect]) + leftBadgePadding;
    if ([self icon]) {
        titleRect.origin.x += iconLength + iconPadding;
        titleRect.size.width -= iconLength + iconPadding;
    }
    return titleRect;
}

-(NSRect)imageRectForBounds:(NSRect)theRect {
    if (![self icon])
        return NSZeroRect;
    NSRect imageRect = [super titleRectForBounds:theRect];
    imageRect.size.width = iconLength;
    imageRect.origin.y += (NSHeight(imageRect) - iconLength) / 2;
    imageRect.size.height = iconLength;
    return imageRect;
}

-(NSRect)badgeRectForBounds:(NSRect)theRect {
    NSAttributedString *badgeText = [self attributedBadgeString];
    NSSize badgeTextSize = [badgeText size];
    NSSize badgeSize = NSMakeSize(badgeTextSize.width + (2 * horizontalBadgeTextPadding), badgeTextSize.height);
    return NSMakeRect(NSMaxX(theRect) - rightBadgePadding - badgeSize.width, NSMinY(theRect) + ((NSHeight(theRect) - badgeSize.height)/2), badgeSize.width, badgeSize.height);
}

-(NSAttributedString *)attributedBadgeString {
    NSMutableDictionary *stringAttributes = [NSMutableDictionary dictionaryWithDictionary:badgeAttributes];
    NSColor *highlightedTextColor = [NSApp isActive] ? badgeTextColorHighlighted : badgeTextColorInactive;
    NSColor *textColor = [self isHighlighted] ? highlightedTextColor : badgeTextColor;
    [stringAttributes setValue:textColor forKey:NSForegroundColorAttributeName];
    return [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%i", [self itemCount]] attributes:stringAttributes];
}

- (void)addTrackingAreasForView:(NSView *)view inRect:(NSRect)cellFrame withUserInfo:(NSDictionary *)userInfo mouseLocation:(NSPoint)currentPoint {
    if ([[self representedObject] isKindOfClass:[RNSourceListPlaceholder class]]) 
        [[self hoverButtonCell] addTrackingAreasForView:view inRect:[self titleRectForBounds:cellFrame] withUserInfo:userInfo mouseLocation:currentPoint];
}

- (void)mouseEntered:(NSEvent *)event {
    [[self hoverButtonCell] mouseEntered:event];
    [(NSControl *)[self controlView] updateCell:self];
}

- (void)mouseExited:(NSEvent *)event {
    [[self hoverButtonCell] mouseExited:event];
    [(NSControl *)[self controlView] updateCell:self];
}

- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView {
    if (![[self representedObject] isKindOfClass:[RNSourceListPlaceholder class]])
        return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];
    NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
    NSRect sourceListCellRect = [self titleRectForBounds:cellFrame];
    NSRect hoverCellRect = [self titleRectForBounds:sourceListCellRect];
    if ([controlView mouse:point inRect:hoverCellRect]) {
        return NSCellHitContentArea | NSCellHitTrackableArea;
    }
    return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];
}

-(BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp {
    return [[self hoverButtonCell] trackMouse:theEvent inRect:[self titleRectForBounds:cellFrame] ofView:controlView untilMouseUp:untilMouseUp];
}

@end
